from flask import current_app, jsonify, render_template, abort, session, g, request
from . import news_blue
from info import models, db
from info.utils.response_code import RET
from ...utils.commons import user_login_data


@news_blue.route('/<int:news_id>')
@user_login_data
def news_detail(news_id):
    try:
        # # 0,从session中获取到user_id，并根据user_id获取到用户信息
        # user_id = session.get('user_id')
        # user = models.User.query.get(user_id)
        # 1,根据新闻编号，查询新闻对象
        try:
            news = models.News.query.get(news_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="获取新闻失败")
        # 2. 如果新闻对象不存在直接抛出异常
        if not news:
            abort(404)
        # 获取前6条热点新闻
        click_news = models.News.query.order_by(models.News.clicks.desc()).limit(6)
        click_news_list = []
        for item in click_news:
            click_news_list.append(item.to_dict())

        # 判断是否用户收藏过该新闻
        is_collected = False
        if g.user:
            if news in g.user.collection_news:
                is_collected = True
        # 查询数据库所有的评论
        try:
            comments = models.Comment.query.filter(models.Comment.news_id == news_id).order_by(
                models.Comment.create_time.desc()).all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='获取评论失败！')

        # 6.1 用户点赞过的评论编号
        try:
            # 6.1.1 该用户点过所有的赞
            commentlikes = []
            if g.user:
                commentlikes = models.CommentLike.query.filter(models.CommentLike.user_id == g.user.id).all()
            # 6.1.2获取用户所有点赞过的评论编号
            mylike_comment_ids = []
            for commentLike in commentlikes:
                mylike_comment_ids.append(commentLike.comment_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="获取点赞失败")
        # 将评论的对象列表，转换成字典列表
        comment_list = []
        for comment in comments:
            comment_dict = comment.to_dict()
            comment_dict['is_like'] = False
            # 判断用户是否对评论点过赞
            if g.user and comment.id in mylike_comment_ids:
                comment_dict['is_like'] = True
            comment_list.append(comment_dict)
        is_followed = False
        if g.user and news.user:
            if g.user in news.user.followers:
                is_followed = True
        # 2.携带数据，渲染页面
        data = {
            "news_info": news.to_dict(),
            "user_info": g.user.to_dict() if g.user else '',
            "news": click_news_list,
            "is_collected": is_collected,
            "comments": comment_list,
            "is_followed": is_followed
        }
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.UNKOWNERR, errmsg='未知错误！')
    return render_template("news/detail.html", data=data)


# 收藏功能的实现
@news_blue.route('/news_collect', methods=['POST'])
@user_login_data
def news_collect():
    # 1. 判断用户是否登陆了
    if not g.user:
        return jsonify(errno=RET.NODATA, errmsg='用户未登录！')
    # 2. 获取参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    # 3. 参数校验，为空校验
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误！')
    # 4. 操作类型校验
    if not action in ['collect', 'cancel_collect']:
        return jsonify(errno=RET.DATAERR, errmsg='操作类型有误！')
    # 5. 根据新闻的编号取出新闻对象
    news_obj = models.News.query.get(news_id)
    # 6. 判断新闻对象是否存在
    if not news_obj:
        return jsonify(errno=RET.DATAERR, errmsg='该新闻不存在！')
    # 7. 根据操作类型，进行收藏或取消收藏操作
    if action == 'collect':
        if not news_obj in g.user.collection_news:
            g.user.collection_news.append(news_obj)
            db.session.commit()
    else:
        if not news_obj in g.user.collection_news:
            g.user.collection_news.remove(news_obj)
            db.session.commit()
    # 8. 返回响应
    return jsonify(errno=RET.OK, errmsg='收藏成功！')


# 评论的功能
@news_blue.route('/news_comment', methods=['POST'])
@user_login_data
def news_comment():
    try:
        # 1, 判断用户是否登陆
        if not g.user:
            return jsonify(errno=RET.NODATA, errmsg='用户未登录！')
        # 2, 获取请求参数
        news_id = request.json.get("news_id")
        content = request.json.get("comment")
        parent_id = request.json.get("parent_id")
        print(news_id, content)
        # 3, 校验参数，为空校验
        if not all([news_id, content]):
            return jsonify(errno=RET.PARAMERR, errmsg='参数错误！')
        # 4, 根据新闻编号取出新闻对象，判断新闻是否存在
        news_obj = models.News.query.get(news_id)
        if not news_obj:
            return jsonify(errno=RET.DATAERR, errmsg='该新闻不存在！')
        # 5, 创建评论对象，设置属性
        comment = models.Comment()
        comment.user_id = g.user.id
        comment.news_id = news_id
        comment.content = content
        if parent_id:
            comment.parent_id = parent_id
        # 6, 保存评论对象到数据库中
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.UNKOWNERR, errmsg='未知错误！')
    # 7, 返回响应，携带评论的数据
    return jsonify(errno=RET.OK, errmsg='评论成功！', data=comment.to_dict())


# 点赞的功能
@news_blue.route('/comment_like', methods=['POST'])
@user_login_data
def comment_like():
    try:
        # 1. 判断用户是否登录
        if not g.user:
            return jsonify(errno=RET.NODATA, errmsg='用户未登录！')
        # 2. 获取参数
        comment_id = request.json.get('comment_id')
        action = request.json.get('action')
        # 3. 参数校验，为空校验
        if not all([comment_id, action]):
            return jsonify(errno=RET.NODATA, errmsg='参数不存在！')
        # 4. 操作类型校验
        if action not in ['add', 'remove']:
            return jsonify(errno=RET.DATAERR, errmsg='操作类型错误！')
        # 5. 通过评论编号查询评论对象，并判断是否存在
        try:
            comments = models.Comment.query.get(comment_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg="获取评论失败！")
        if not comments:
            return jsonify(errno=RET.DATAERR, errmsg='该评论不存在！')
        # 6. 根据操作类型点赞取消点赞
        if action == 'add':
            # 判断是否已经点过赞了
            comment_like = models.CommentLike.query.filter(models.CommentLike.user_id == g.user.id,
                                                           models.CommentLike.comment_id == comment_id)
            if not comment_like:
                comment_like = models.CommentLike()
                comment_like.user_id = g.user.id
                comment_like.comment_id = comment_id
                db.session.add(comment_like)

                # 将该评论的点赞数加一
                comments.like_count += 1

                db.session.commit()
        else:
            # 判断是否已经点过赞了
            comment_like = models.CommentLike.query.filter(models.CommentLike.user_id == g.user.id,
                                                           models.CommentLike.comment_id == comment_id)
            if comment_like:
                db.session.delete(comment_like)

                # 将该评论的点赞数减一
                if comments.like_count > 0:
                    comments.like_count -= 1

                db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.UNKOWNERR, errmsg='未知错误！')
    # 7. 返回响应
    return jsonify(errno=RET.OK, errmsg='点赞成功！')


# 关注取消关注
@news_blue.route('/followed_user', methods=['POST'])
@user_login_data
def followed_user():
    if not g.user:
        return jsonify(errno=RET.NODATA, errmsg='用户未登录')

    author_id = request.json.get('user_id')
    action = request.json.get('action')

    if not all([author_id, action]):
        return jsonify(errno=RET.NODATA, errmsg='参数不全！')

    if action not in ['follow', 'unfollow']:
        return jsonify(errno=RET.DATAERR, errmsg='操作类型错误！')

    try:
        author = models.User.query.get(author_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询作者失败！')

    if not author: return jsonify(errno=RET.NODATA, errmsg='该作者不存在！')

    if action == 'follow':
        if not g.user in author.followers:
            author.followers.append(g.user)
    else:
        if g.user in author.follows:
            author.followers.remove(g.user)

    return jsonify(errno=RET.OK, errmsg='操作成功！')
